/* Turska UI library
 * Copyright 2003-2008 Jetro Lauha
 * All rights reserved.
 * Web: http://iki.fi/jetro/ or http://jet.ro
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of EITHER:
 *   (1) The GNU Lesser General Public License as published by the Free
 *       Software Foundation; either version 2.1 of the License, or (at
 *       your option) any later version. The text of the GNU Lesser
 *       General Public License is included with this library in the
 *       file LICENSE-LGPL.txt.
 *   (2) The BSD-style license that is included with this library in
 *       the file LICENSE-BSD.txt.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
 * LICENSE-LGPL.txt and LICENSE-BSD.txt for more details.
 *
 * $Id: UIImageOpenGL.cpp,v 1.6 2008/03/27 11:44:28 tonic Exp $
 * $Revision: 1.6 $
 */

// SDL is included here only for the OpenGL.
#include "SDL.h"
#include "SDL_opengl.h"

#include "UI.h"


UIImageOpenGL::UIImageOpenGL(UINT32 width, UINT32 height, UINT32 flags,
                             UINT glId, const FLOAT *uv) :
    UIImage(width, height, NORMAL, flags),
    mGLId(glId),
    mNegHalfWidth(-0.5f * width),
    mNegHalfHeight(-0.5f * height),
    mPosHalfWidth(0.5f * width),
    mPosHalfHeight(0.5f * height),
    mTargetWidth(width),
    mTargetHeight(height),
    mAngle(0),
    mScaleX(1), mScaleY(1),
    mPivotX(0), mPivotY(0)  // pivot reference point is center of image
{
    INT a;
    for (a = 0; a < 4; ++a)
    {
        mColor[a] = 1.0f;
        mUV[a] = uv[a];
    }
}


UIImageOpenGL::~UIImageOpenGL()
{
    glDeleteTextures(1, (const GLuint *)&mGLId);
}


void UIImageOpenGL::setColor(UINT8 red, UINT8 green, UINT8 blue, UINT8 alpha)
{
    setColor(red / 255.f, green / 255.f, blue / 255.f, alpha / 255.f);
}


void UIImageOpenGL::draw(UINT drawMode, UINT32 flags, FLOAT x, FLOAT y,
                         FLOAT red, FLOAT green, FLOAT blue, FLOAT alpha)
{
    const FLOAT color[4] = { red, green, blue, alpha };
    draw(drawMode, flags, x, y, color);
}


void UIImageOpenGL::draw(UINT drawMode, UINT32 flags, FLOAT x, FLOAT y, const FLOAT *color)
{
    // storeMatrix will be >0 if TRANSFORM and at least one of ROTATE, CENTER or SCALE is enabled.
    UINT32 storeMatrix = (flags & TRANSFORM) ? (flags & (ROTATE | CENTER | SCALE)) : 0;
    // drawMode 0 (NORMAL) doesn't need storing of attributes, other drawModes need it.
    const UINT storeAttrib = drawMode;

    if (storeAttrib)
        glPushAttrib(GL_COLOR_BUFFER_BIT);

    switch (drawMode)
    {
    case ADD:
        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        break;
    case MULTIPLY:
        glBlendFunc(GL_ZERO, GL_SRC_COLOR);
        break;
    default:;
        // blend func is assumed to be (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) by default
    }

    if (storeMatrix)
        glPushMatrix();

    // Note: COLOR flag is currently ignored in this implementation.
    glColor4fv(color);

    glBindTexture(GL_TEXTURE_2D, mGLId);

    if (flags & TRANSFORM)
    {
        glTranslatef(x, y, 0);
        if (flags & ROTATE)
            glRotatef(mAngle * (180 / 3.1415926535897932f), 0, 0, 1);
        if (flags & SCALE)
            glScalef(mScaleX, mScaleY, 0);

        glBegin(GL_TRIANGLE_STRIP);
        if (flags & CENTER)
        {
            glTexCoord2f(mUV[0], mUV[1]); glVertex2f(mNegHalfWidth - mPivotX, mNegHalfHeight - mPivotY);
            glTexCoord2f(mUV[2], mUV[1]); glVertex2f(mPosHalfWidth - mPivotX, mNegHalfHeight - mPivotY);
            glTexCoord2f(mUV[0], mUV[3]); glVertex2f(mNegHalfWidth - mPivotX, mPosHalfHeight - mPivotY);
            glTexCoord2f(mUV[2], mUV[3]); glVertex2f(mPosHalfWidth - mPivotX, mPosHalfHeight - mPivotY);
        }
        else
        {
            glTexCoord2f(mUV[0], mUV[1]); glVertex2f(0, 0);
            glTexCoord2f(mUV[2], mUV[1]); glVertex2f(mWidth, 0);
            glTexCoord2f(mUV[0], mUV[3]); glVertex2f(0, mHeight);
            glTexCoord2f(mUV[2], mUV[3]); glVertex2f(mWidth, mHeight);
        }
        glEnd();
    }
    else
    {
        glBegin(GL_TRIANGLE_STRIP);
        glTexCoord2f(mUV[0], mUV[1]); glVertex2f(x, y);
        glTexCoord2f(mUV[2], mUV[1]); glVertex2f(x + mTargetWidth, y);
        glTexCoord2f(mUV[0], mUV[3]); glVertex2f(x, y + mTargetHeight);
        glTexCoord2f(mUV[2], mUV[3]); glVertex2f(x + mTargetWidth, y + mTargetHeight);
        glEnd();
    }

    if (storeMatrix)
        glPopMatrix();
    if (storeAttrib)
        glPopAttrib();
}
